package handler

import (
	"crypto/rand"
	"encoding/base64"
	"net/http"
	"strconv"
	"strings"
	"time"

	"project-info/src/handle/response"
	"project-info/src/model"

	"project-info/src/lib"
)

// ClientRequest 客户端请求结构
type ClientRequest struct {
	Id                      uint64   `json:"id,omitempty"`
	ClientId                string   `json:"clientId,omitempty"`
	ClientSecret            string   `json:"clientSecret,omitempty"`
	ClientName              string   `json:"clientName,omitempty" form:"clientName"`
	ClientType              string   `json:"clientType,omitempty"`
	RedirectUris            []string `json:"redirectUris,omitempty"`
	GrantTypes              []string `json:"grantTypes,omitempty"`
	ResponseTypes           []string `json:"responseTypes,omitempty"`
	Scopes                  []string `json:"scopes,omitempty"`
	TokenEndpointAuthMethod string   `json:"tokenEndpointAuthMethod,omitempty"`
	AccessTokenTtl          int      `json:"accessTokenTtl,omitempty"`
	RefreshTokenTtl         int      `json:"refreshTokenTtl,omitempty"`
	IdTokenTtl              int      `json:"idTokenTtl,omitempty"`
	Status                  int      `json:"status,omitempty" form:"status"`
	Description             string   `json:"description,omitempty"`
}

// ClientResponse 客户端响应结构
type ClientResponse struct {
	ID                      uint      `json:"id"`
	ClientId                string    `json:"clientId"`
	ClientSecret            string    `json:"clientSecret,omitempty"`
	ClientName              string    `json:"clientName"`
	ClientType              string    `json:"clientType"`
	RedirectUris            []string  `json:"redirectUris"`
	GrantTypes              []string  `json:"grantTypes"`
	ResponseTypes           []string  `json:"responseTypes"`
	Scopes                  []string  `json:"scopes"`
	TokenEndpointAuthMethod string    `json:"tokenEndpointAuthMethod"`
	AccessTokenTtl          int       `json:"accessTokenTtl"`
	RefreshTokenTtl         int       `json:"refreshTokenTtl"`
	IdTokenTtl              int       `json:"idTokenTtl"`
	Status                  int       `json:"status"`
	Description             string    `json:"description"`
	CreateTime              time.Time `json:"createTime"`
	UpdateTime              time.Time `json:"updateTime,omitempty"`
	Creator                 string    `json:"creator,omitempty"`
	Modifier                string    `json:"modifier,omitempty"`
}

// ClientListResponse 客户端列表响应结构
type ClientListResponse struct {
	Clients    []ClientResponse `json:"clients"`
	TotalCount int              `json:"totalCount"`
	Page       int              `json:"page"`
	Size       int              `json:"size"`
}

// ListClients 获取客户端列表
// GET /oidc/admin/clients
func ListClients(c *lib.GinContext) error {
	// 获取分页参数
	pagination := parsePaginationParams(c)
	var req ClientRequest
	if err := c.BindQuery(&req); err != nil {
		return response.JsonFail(c, "参数绑定失败")
	}

	// 使用服务层方法获取客户端列表
	oidcClients, total, err := oidcService.ListClients(req.ClientName, req.Status, pagination.Page, pagination.Size)
	if err != nil {
		return response.JsonFail(c, "获取客户端列表失败")
	}

	clients := make([]ClientResponse, 0)
	for _, oidcClient := range oidcClients {
		client := ClientResponse{
			ID:                      uint(oidcClient.Id),
			ClientId:                oidcClient.ClientID,
			ClientName:              oidcClient.ClientName,
			ClientType:              "confidential", // 默认值
			RedirectUris:            []string(oidcClient.RedirectURIs),
			GrantTypes:              []string(oidcClient.GrantTypes),
			ResponseTypes:           []string(oidcClient.ResponseTypes),
			Scopes:                  []string(oidcClient.Scopes),
			TokenEndpointAuthMethod: oidcClient.TokenEndpointAuthMethod,
			AccessTokenTtl:          oidcClient.AccessTokenTTL,
			RefreshTokenTtl:         oidcClient.RefreshTokenTTL,
			IdTokenTtl:              oidcClient.IDTokenTTL,
			Status:                  oidcClient.Status,
			Description:             oidcClient.Description,
			CreateTime:              *oidcClient.CreateTime,
			Creator:                 oidcClient.Creator,
		}

		if oidcClient.UpdateTime != nil {
			client.UpdateTime = *oidcClient.UpdateTime
			client.Modifier = oidcClient.Modifier
		}

		clients = append(clients, client)
	}

	r := ClientListResponse{
		Clients:    clients,
		TotalCount: int(total),
		Page:       pagination.Page,
		Size:       pagination.Size,
	}

	return response.JsonOk(c, r, "获取成功")
}

// GetClient 获取单个客户端信息
// GET /oidc/admin/clients/:id
func GetClient(c *lib.GinContext) error {
	idStr := c.QueryParam("id")
	if idStr == "" {
		return response.JsonFail(c, "缺少客户端ID参数")
	}

	id, err := strconv.ParseUint(idStr, 10, 64)
	if err != nil {
		return response.JsonFail(c, "客户端ID参数无效")
	}

	// 使用服务层方法获取客户端信息
	oidcClient, err := oidcService.GetClientById(id)
	if err != nil {
		return response.JsonFail(c, "客户端不存在")
	}

	client := ClientResponse{
		ID:                      uint(oidcClient.Id),
		ClientId:                oidcClient.ClientID,
		ClientName:              oidcClient.ClientName,
		ClientType:              "confidential", // 默认值
		RedirectUris:            []string(oidcClient.RedirectURIs),
		GrantTypes:              []string(oidcClient.GrantTypes),
		ResponseTypes:           []string(oidcClient.ResponseTypes),
		Scopes:                  []string(oidcClient.Scopes),
		TokenEndpointAuthMethod: oidcClient.TokenEndpointAuthMethod,
		AccessTokenTtl:          oidcClient.AccessTokenTTL,
		RefreshTokenTtl:         oidcClient.RefreshTokenTTL,
		IdTokenTtl:              oidcClient.IDTokenTTL,
		Status:                  oidcClient.Status,
		Description:             oidcClient.Description,
		CreateTime:              *oidcClient.CreateTime,
		Creator:                 oidcClient.Creator,
	}

	if oidcClient.UpdateTime != nil {
		client.UpdateTime = *oidcClient.UpdateTime
		client.Modifier = oidcClient.Modifier
	}

	return response.JsonOk(c, client, "获取成功")
}

// CreateClient 创建新客户端
// POST /oidc/admin/clients
func CreateClient(c *lib.GinContext) error {
	var req ClientRequest
	if err := c.Bind(&req); err != nil {
		return response.JsonFail(c, "参数错误")
	}

	// 验证重定向URI
	if len(req.RedirectUris) == 0 {
		return response.JsonFail(c, "至少需要一个重定向URI")
	}

	// 验证重定向URI格式
	for _, uri := range req.RedirectUris {
		if !isValidURI(uri) {
			return response.JsonFail(c, "重定向URI格式无效")
		}
	}

	// 设置默认值
	if len(req.Scopes) == 0 {
		req.Scopes = []string{"openid", "profile"}
	}
	if len(req.GrantTypes) == 0 {
		req.GrantTypes = []string{"authorization_code"}
	}

	clientSecret, err := generateClientSecret()
	if err != nil {
		return response.JsonFail(c, "生成客户端密钥失败")
	}

	// 构建客户端对象
	oidcClient := &model.OIDCClient{
		ClientID:                req.ClientId,
		ClientSecret:            clientSecret,
		ClientName:              req.ClientName,
		RedirectURIs:            model.JSONArray(req.RedirectUris),
		Scopes:                  model.JSONArray(req.Scopes),
		GrantTypes:              model.JSONArray(req.GrantTypes),
		ResponseTypes:           model.JSONArray(req.ResponseTypes),
		TokenEndpointAuthMethod: req.TokenEndpointAuthMethod,
		AccessTokenTTL:          req.AccessTokenTtl,
		RefreshTokenTTL:         req.RefreshTokenTtl,
		IDTokenTTL:              req.IdTokenTtl,
		Status:                  req.Status,
		Description:             req.Description,
	}

	// 使用服务层方法创建客户端
	if err := oidcService.CreateClient(oidcClient); err != nil {
		return response.JsonFail(c, "创建客户端失败")
	}

	// 返回客户端信息（包含密钥）
	client := ClientResponse{
		ID:                      uint(oidcClient.Id),
		ClientId:                req.ClientId,
		ClientSecret:            clientSecret,
		ClientName:              req.ClientName,
		ClientType:              req.ClientType,
		RedirectUris:            req.RedirectUris,
		GrantTypes:              req.GrantTypes,
		ResponseTypes:           req.ResponseTypes,
		Scopes:                  req.Scopes,
		TokenEndpointAuthMethod: req.TokenEndpointAuthMethod,
		AccessTokenTtl:          req.AccessTokenTtl,
		RefreshTokenTtl:         req.RefreshTokenTtl,
		IdTokenTtl:              req.IdTokenTtl,
		Status:                  req.Status,
		Description:             req.Description,
		CreateTime:              *oidcClient.CreateTime,
	}

	return response.JsonOk(c, client, "创建成功")
}

// UpdateClient 更新客户端信息
// PUT /oidc/admin/clients/
func UpdateClient(c *lib.GinContext) error {
	var req ClientRequest
	if err := c.Bind(&req); err != nil {
		return response.JsonFail(c, "参数错误")
	}

	// 验证客户端是否存在
	client, err := oidcService.GetClientById(req.Id)
	if err != nil {
		return response.JsonFail(c, "客户端不存在")
	}

	// 验证重定向URI
	if len(req.RedirectUris) == 0 {
		return response.JsonFail(c, "至少需要一个重定向URI")
	}

	// 验证重定向URI格式
	for _, uri := range req.RedirectUris {
		if !isValidURI(uri) {
			return response.JsonFail(c, "重定向URI格式无效")
		}
	}

	// 设置默认值
	if len(req.Scopes) == 0 {
		req.Scopes = []string{"openid", "profile"}
	}
	if len(req.GrantTypes) == 0 {
		req.GrantTypes = []string{"authorization_code"}
	}

	// 构建更新数据
	updates := map[string]interface{}{
		"client_name":                req.ClientName,
		"client_id":                  req.ClientId,
		"client_type":                req.ClientType,
		"redirect_uris":              model.JSONArray(req.RedirectUris),
		"scopes":                     model.JSONArray(req.Scopes),
		"grant_types":                model.JSONArray(req.GrantTypes),
		"response_types":             model.JSONArray(req.ResponseTypes),
		"token_endpoint_auth_method": req.TokenEndpointAuthMethod,
		"access_token_ttl":           req.AccessTokenTtl,
		"refresh_token_ttl":          req.RefreshTokenTtl,
		"id_token_ttl":               req.IdTokenTtl,
		"status":                     req.Status,
		"description":                req.Description,
	}

	if req.ClientSecret != "" {
		updates["client_secret"] = req.ClientSecret
	}

	// 使用服务层方法更新客户端
	if err = oidcService.UpdateClient(req.Id, updates); err != nil {
		return response.JsonFail(c, "更新客户端失败")
	}

	// 重新获取更新后的客户端信息
	oidcClient, err := oidcService.GetClient(client.ClientID)
	if err != nil {
		return response.JsonFail(c, "获取更新后的客户端信息失败")
	}

	// 返回更新后的客户端信息（不包含密钥）
	r := ClientResponse{
		ID:                      uint(oidcClient.Id),
		ClientId:                client.ClientID,
		ClientName:              req.ClientName,
		ClientType:              req.ClientType,
		RedirectUris:            req.RedirectUris,
		GrantTypes:              req.GrantTypes,
		ResponseTypes:           req.ResponseTypes,
		Scopes:                  req.Scopes,
		TokenEndpointAuthMethod: req.TokenEndpointAuthMethod,
		AccessTokenTtl:          req.AccessTokenTtl,
		RefreshTokenTtl:         req.RefreshTokenTtl,
		IdTokenTtl:              req.IdTokenTtl,
		Status:                  req.Status,
		Description:             req.Description,
		CreateTime:              *oidcClient.CreateTime,
		UpdateTime:              *oidcClient.UpdateTime,
	}

	return response.JsonOk(c, r, "更新成功")
}

// DeleteClient 删除客户端
// DELETE /oidc/admin/clients/
func DeleteClient(c *lib.GinContext) error {
	id, err := strconv.ParseUint(c.QueryParam("id"), 10, 64)
	if err != nil {
		return response.JsonFail(c, "缺少客户端ID参数")
	}

	// 使用服务层方法删除客户端
	if err := oidcService.DeleteClient(id); err != nil {
		return response.JsonFail(c, "删除客户端失败")
	}

	return response.JsonOk(c, nil, "删除成功")
}

// RegenerateClientSecret 重新生成客户端密钥
// POST /oidc/admin/clients/regenerate-secret
func RegenerateClientSecret(c *lib.GinContext) error {
	id, err := strconv.ParseUint(c.QueryParam("id"), 10, 64)
	if err != nil {
		return response.JsonFail(c, "缺少客户端ID参数")
	}

	// 使用服务层方法重新生成客户端密钥
	newSecret, err := oidcService.RegenerateClientSecret(id)
	if err != nil {
		return response.JsonFail(c, "重新生成客户端密钥失败")
	}

	return response.JsonOk(c, map[string]interface{}{
		"id":           id,
		"clientSecret": newSecret,
	}, "客户端密钥重新生成成功，所有现有令牌已被撤销")
}

// GetClientStats 获取客户端统计信息
// GET /oidc/admin/clients/:id/stats
func GetClientStats(c *lib.GinContext) error {
	id, err := strconv.ParseUint(c.QueryParam("id"), 10, 64)
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]interface{}{
			"error":             "invalid_request",
			"error_description": "Missing client_id parameter",
		})
	}

	// 使用服务层方法获取客户端统计信息
	stats, err := oidcService.GetClientStats(id)
	if err != nil {
		return c.JSON(http.StatusNotFound, map[string]interface{}{
			"error":             "client_not_found",
			"error_description": "Client not found",
		})
	}

	return response.JsonOk(c, stats, "获取成功")
}

// generateClientSecret 生成客户端密钥
func generateClientSecret() (string, error) {
	bytes := make([]byte, 32)
	_, err := rand.Read(bytes)
	if err != nil {
		return "", err
	}
	return base64.URLEncoding.EncodeToString(bytes), nil
}

// isValidURI 验证URI格式
func isValidURI(uri string) bool {
	// 简化的URI验证
	return strings.HasPrefix(uri, "http://") || strings.HasPrefix(uri, "https://")
}
